﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace BUGCOME.Common
{
    /// <summary>
    /// 工具类，提供字符串处理、日期计算、正则验证等通用功能
    /// </summary>
    public class Tools
    {
        /// <summary>
        /// 将DateTime转换为相对时间描述（如"今天"、"3小时前"、"2年前"）
        /// </summary>
        /// <param name="time">需要转换的目标时间</param>
        /// <returns>相对时间字符串</returns>
        public static string GetRelativeTime(DateTime time)
        {
            var span = DateTime.Now - time;

            // 按时间差优先级计算（从高到低：年 → 月 → 天）
            if (span.TotalDays >= 365)
            {
                int years = (int)(span.TotalDays / 365);
                return $"{years}年前";
            }
            else if (span.TotalDays >= 30)
            {
                int months = (int)(span.TotalDays / 30); // 简化计算，未按实际月份天数调整
                return $"{months}个月前";
            }
            else if (span.TotalDays >= 1)
            {
                return $"{(int)span.TotalDays}天前";
            }
            else if (span.TotalHours >= 1)
            {
                return $"{(int)span.TotalHours}小时前";
            }
            else
            {
                return "今天"; // 当天数据
            }
        }

        /// <summary>
        /// 将字符串按指定分隔符分割并转换为长整型数组
        /// </summary>
        /// <param name="str">待分割的字符串（示例："1,3,10,00"）</param>
        /// <param name="split">分隔符，默认逗号</param>
        /// <returns>长整型数组，空字符串返回空数组</returns>
        public static long[] SpitLongArrary(string str, char split = ',')
        {
            if (string.IsNullOrEmpty(str)) { return Array.Empty<long>(); }
            str = str.TrimStart(split).TrimEnd(split);
            string[] strIds = str.Split(split, (char)StringSplitOptions.RemoveEmptyEntries);
            long[] infoIdss = Array.ConvertAll(strIds, s => long.Parse(s));
            return infoIdss;
        }

        /// <summary>
        /// 将字符串按指定分隔符分割并转换为整型数组
        /// </summary>
        /// <param name="str">待分割的字符串</param>
        /// <param name="split">分隔符，默认逗号</param>
        /// <returns>整型数组，空字符串返回空数组</returns>
        public static int[] SplitIntArray(string str, char split = ',')
        {
            if (string.IsNullOrEmpty(str)) { return Array.Empty<int>(); }
            string[] strIds = str.Split(split, (char)StringSplitOptions.RemoveEmptyEntries);
            int[] infoIdss = Array.ConvertAll(strIds, s => int.Parse(s));
            return infoIdss;
        }

        /// <summary>
        /// 通用类型转换分割方法，支持将字符串按分隔符转换为指定类型数组
        /// </summary>
        /// <typeparam name="T">目标数据类型</typeparam>
        /// <param name="input">待分割的字符串</param>
        /// <param name="split">分隔符，默认逗号</param>
        /// <returns>指定类型的数组，空字符串返回空数组</returns>
        public static T[] SplitAndConvert<T>(string input, char split = ',')
        {
            if (string.IsNullOrEmpty(input)) { return Array.Empty<T>(); }
            string[] parts = input.Split(split, (char)StringSplitOptions.RemoveEmptyEntries);
            T[] result = Array.ConvertAll(parts, s => (T)Convert.ChangeType(s, typeof(T)));
            return result;
        }

        /// <summary>
        /// 根据日期获取对应的星期几（中文）
        /// </summary>
        /// <param name="dt">目标日期</param>
        /// <returns>星期几的中文描述（如"星期日"）</returns>
        public static string GetWeekByDate(DateTime dt)
        {
            var day = new[] { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
            return day[Convert.ToInt32(dt.DayOfWeek.ToString("d"))];
        }

        /// <summary>
        /// 计算指定日期在当月中的周数（第几周）
        /// </summary>
        /// <param name="daytime">目标日期</param>
        /// <returns>当月周数（从1开始计数）</returns>
        public static int GetWeekNumInMonth(DateTime daytime)
        {
            int dayInMonth = daytime.Day;
            // 本月第一天
            DateTime firstDay = daytime.AddDays(1 - daytime.Day);
            // 本月第一天是周几（1-7，周日为7）
            int weekday = (int)firstDay.DayOfWeek == 0 ? 7 : (int)firstDay.DayOfWeek;
            // 本月第一周包含的天数
            int firstWeekEndDay = 7 - (weekday - 1);
            // 当前日期与第一周结束日的差值
            int diffday = dayInMonth - firstWeekEndDay;
            diffday = diffday > 0 ? diffday : 1;
            // 计算周数（整除7时调整计数逻辑）
            int weekNumInMonth = ((diffday % 7) == 0
                ? (diffday / 7 - 1)
                : (diffday / 7)) + 1 + (dayInMonth > firstWeekEndDay ? 1 : 0);
            return weekNumInMonth;
        }

        /// <summary>
        /// 判断字符串是否为合法URL格式
        /// </summary>
        /// <param name="str">待验证字符串</param>
        /// <returns>验证结果（true为合法URL）</returns>
        public static bool IsUrl(string str)
        {
            try
            {
                string Url = @"^http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?$";
                return Regex.IsMatch(str, Url);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 验证用户名格式是否合法（6-32位，支持字母、数字、下划线、点、@）
        /// </summary>
        /// <param name="str">待验证用户名</param>
        /// <returns>验证结果（true为合法格式）</returns>
        public static bool CheckUserName(string str)
        {
            try
            {
                string rg = @"^[a-zA-Z0-9_.@]{6,32}$";
                return Regex.IsMatch(str, rg);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 验证密码强度是否符合要求（8-16位，包含大小写字母、数字、特殊字符）
        /// </summary>
        /// <param name="password">待验证密码</param>
        /// <returns>验证结果（true为符合强度要求）</returns>
        public static bool PasswordStrength(string password)
        {
            try
            {
                string rg = @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*(),.?"":{}|<>])[A-Za-z\d!@#$%^&*(),.?"":{}|<>]{8,16}$";
                return Regex.IsMatch(password, rg);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 生成指定长度的随机字符串，支持自定义字符集
        /// </summary>
        /// <param name="length">目标字符串长度，默认6位</param>
        /// <param name="useNum">是否包含数字，默认包含</param>
        /// <param name="useLow">是否包含小写字母，默认不包含</param>
        /// <param name="useUpp">是否包含大写字母，默认不包含</param>
        /// <param name="useSpe">是否包含特殊字符，默认不包含</param>
        /// <param name="custom">自定义字符集，直接输入包含的字符</param>
        /// <returns>生成的随机字符串</returns>
        public static string GetRandomString(int length = 6, bool useNum = true, bool useLow = false, bool useUpp = false, bool useSpe = false, string custom = "")
        {
            byte[] b = new byte[4];
            System.Security.Cryptography.RandomNumberGenerator.Create().GetBytes(b);
            Random r = new(BitConverter.ToInt32(b, 0));
            string s = null, str = custom;
            if (useNum == true) { str += "0123456789"; }
            if (useLow == true) { str += "abcdefghijklmnopqrstuvwxyz"; }
            if (useUpp == true) { str += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; }
            if (useSpe == true) { str += "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; }
            for (int i = 0; i < length; i++)
            {
                s += str.Substring(r.Next(0, str.Length - 1), 1);
            }
            return s;
        }

        /// <summary>
        /// 将标准GUID字符串按分隔符'-'拆分为5个部分
        /// 0: 密码加密密钥
        /// 1: 内部加密密钥
        /// 2: 外部加密密钥
        /// 3: 聊天加密密钥
        /// 4: 公开加密密钥
        /// </summary>
        /// <param name="guidString">标准格式的GUID字符串（如"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"）</param>
        ///  <param name="character">分割字符 默认 ,</param>
        /// <returns>包含5个部分的列表；若输入为null、空字符串或格式不正确，返回null</returns>
        public static List<string> Split(string guid,string character = ",")
        {
            // 先检查输入是否为null或空字符串
            if (string.IsNullOrEmpty(guid))
                return new List<string>();

            // 拆分GUID并转换为列表
            List<string> segments = guid.Split(character).ToList();

            // 验证拆分后是否正好是5个部分（标准GUID格式）
            return segments.Count == 5 ? segments : new List<string>();
        }
    }
}
